LIBRARY ieee;
USE ieee.std_logic_1164.all;
USE ieee.std_logic_arith.all;
USE ieee.std_logic_unsigned.all;

ENTITY fc_Double_Dabble IS
  GENERIC( 
  n : NATURAL := 64;    -- aantal bits van x
  m : NATURAL := 16      -- aantal cijfers van BCD
  );
  PORT( 
  x         : IN     STD_LOGIC_VECTOR (63 DOWNTO 0);
  start     : IN     STD_LOGIC  := '1';
  conv_time : IN     STD_LOGIC  := '0';
  clk       : IN     STD_LOGIC;
  rst       : IN     STD_LOGIC;
  BCD       : BUFFER STD_LOGIC_VECTOR (m*4-1 DOWNTO 0);
  ready     : OUT    STD_LOGIC
  );
END ENTITY fc_Double_Dabble;

---------------------------------------
---------------------------------------


ARCHITECTURE v OF fc_Double_Dabble IS


SIGNAL cntr  :  NATURAL RANGE 0 TO n;
SIGNAL xreg  :  STD_LOGIC_VECTOR(n-1 DOWNTO 0);


BEGIN
  
  
  
  PROCESS(rst, clk)
    BEGIN
      IF  rst = '1' THEN
        cntr  <= 0;
        xreg  <= (OTHERS => '0');
        
      ELSIF RISING_EDGE(clk) THEN
        
        IF start = '1' THEN
          cntr  <= n;
          xreg  <= x(n-1 DOWNTO 0);
        ELSIF cntr > 0 THEN
          cntr <= cntr -1;
          xreg <= xreg(n-2 DOWNTO 0) & '0';
        END IF;
        
      END IF;
    END PROCESS;
    
    
    
    PROCESS(rst, clk)
      BEGIN
        IF  rst = '1' THEN
          ready <= '0';
          
        ELSIF RISING_EDGE(clk) THEN
          
          IF cntr = 1 THEN
            ready <= '1';
          ELSE
            ready <= '0';
          END IF;
          
        END IF;
      END PROCESS;
      
      
      PROCESS(rst, clk)
        
        VARIABLE q    :  STD_LOGIC_VECTOR(3 DOWNTO 0);
        
        VARIABLE sin  : STD_LOGIC;     
        VARIABLE sout : STD_LOGIC;
        
        BEGIN
          IF  rst = '1' THEN
            BCD <= (OTHERS => '0');
          ELSIF RISING_EDGE(clk) THEN
            
            IF start = '1' THEN
              BCD <= (OTHERS => '0');
            ELSIF cntr > 0 THEN
              
              sin := xreg(n-1);
              
              FOR i in 0 TO m-1 LOOP
                
                q := BCD(i*4+3 DOWNTO i*4);
                
                IF     q >= "0011" AND (i = 3 OR i = 1) AND conv_time = '1' THEN
                  sout := '1';
                ELSIF  q >= "0101" THEN
                  sout := '1';
                ELSE
                  sout := '0';
                END IF;
                
                
                IF sout = '0' THEN
                  q :=   q(2 DOWNTO 0) & sin;
                ELSIF (conv_time = '1' AND (i = 3 OR i = 1)) THEN
                  q := (q(2 DOWNTO 0)-"011") & sin;
                ELSE
                  q := (q(2 DOWNTO 0)-"101") & sin;
                END IF;
                
                BCD(i*4+3 DOWNTO i*4) <= q;
                
                sin := sout;
                
              END LOOP;
              
            END IF;
            
          END IF;
        END PROCESS;
        
     
        
        
        
END ARCHITECTURE v;
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      